home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / Development / ncurses-5.3 / ncurses / base / lib_addch.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-27  |  9.9 KB  |  366 lines

  1. /****************************************************************************
  2.  * Copyright (c) 1998-2001,2002 Free Software Foundation, Inc.              *
  3.  *                                                                          *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a  *
  5.  * copy of this software and associated documentation files (the            *
  6.  * "Software"), to deal in the Software without restriction, including      *
  7.  * without limitation the rights to use, copy, modify, merge, publish,      *
  8.  * distribute, distribute with modifications, sublicense, and/or sell       *
  9.  * copies of the Software, and to permit persons to whom the Software is    *
  10.  * furnished to do so, subject to the following conditions:                 *
  11.  *                                                                          *
  12.  * The above copyright notice and this permission notice shall be included  *
  13.  * in all copies or substantial portions of the Software.                   *
  14.  *                                                                          *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
  16.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
  17.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
  18.  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
  19.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
  20.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
  21.  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
  22.  *                                                                          *
  23.  * Except as contained in this notice, the name(s) of the above copyright   *
  24.  * holders shall not be used in advertising or otherwise to promote the     *
  25.  * sale, use or other dealings in this Software without prior written       *
  26.  * authorization.                                                           *
  27.  ****************************************************************************/
  28.  
  29. /*
  30. **    lib_addch.c
  31. **
  32. **    The routine waddch().
  33. **
  34. */
  35.  
  36. #include <curses.priv.h>
  37. #include <ctype.h>
  38.  
  39. MODULE_ID("$Id: lib_addch.c,v 1.68 2002/09/28 17:48:13 tom Exp $")
  40.  
  41. /*
  42.  * Ugly microtweaking alert.  Everything from here to end of module is
  43.  * likely to be speed-critical -- profiling data sure says it is!
  44.  * Most of the important screen-painting functions are shells around
  45.  * waddch().  So we make every effort to reduce function-call overhead
  46.  * by inlining stuff, even at the cost of making wrapped copies for
  47.  * export.  Also we supply some internal versions that don't call the
  48.  * window sync hook, for use by string-put functions.
  49.  */
  50.  
  51. /* Return bit mask for clearing color pair number if given ch has color */
  52. #define COLOR_MASK(ch) (~(attr_t)((ch)&A_COLOR?A_COLOR:0))
  53.  
  54. static inline NCURSES_CH_T
  55. render_char(WINDOW *win, NCURSES_CH_T ch)
  56. /* compute a rendition of the given char correct for the current context */
  57. {
  58.     attr_t a = win->_attrs;
  59.  
  60.     if (ISBLANK(ch) && AttrOf(ch) == A_NORMAL) {
  61.     /* color in attrs has precedence over bkgrnd */
  62.     ch = win->_nc_bkgd;
  63.     SetAttr(ch, a | (AttrOf(win->_nc_bkgd) & COLOR_MASK(a)));
  64.     } else {
  65.     /* color in attrs has precedence over bkgrnd */
  66.     a |= AttrOf(win->_nc_bkgd) & COLOR_MASK(a);
  67.     /* color in ch has precedence */
  68.     AddAttr(ch, (a & COLOR_MASK(AttrOf(ch))));
  69.     }
  70.  
  71.     TR(TRACE_VIRTPUT, ("bkg = %s, attrs = %s -> ch = %s",
  72.                _tracech_t2(1, CHREF(win->_nc_bkgd)),
  73.                _traceattr(win->_attrs),
  74.                _tracech_t2(3, CHREF(ch))));
  75.  
  76.     return (ch);
  77. }
  78.  
  79. NCURSES_EXPORT(NCURSES_CH_T)
  80. _nc_render(WINDOW *win, NCURSES_CH_T ch)
  81. /* make render_char() visible while still allowing us to inline it below */
  82. {
  83.     return render_char(win, ch);
  84. }
  85.  
  86. /* check if position is legal; if not, return error */
  87. #ifndef NDEBUG            /* treat this like an assertion */
  88. #define CHECK_POSITION(win, x, y) \
  89.     if (y > win->_maxy \
  90.      || x > win->_maxx \
  91.      || y < 0 \
  92.      || x < 0) { \
  93.         TR(TRACE_VIRTPUT, ("Alert! Win=%p _curx = %d, _cury = %d " \
  94.                    "(_maxx = %d, _maxy = %d)", win, x, y, \
  95.                    win->_maxx, win->_maxy)); \
  96.         return(ERR); \
  97.     }
  98. #else
  99. #define CHECK_POSITION(win, x, y)    /* nothing */
  100. #endif
  101.  
  102. static inline int
  103. waddch_literal(WINDOW *win, NCURSES_CH_T ch)
  104. {
  105.     int x;
  106.     struct ldat *line;
  107.  
  108.     x = win->_curx;
  109.  
  110.     CHECK_POSITION(win, x, win->_cury);
  111.  
  112.     /*
  113.      * If we're trying to add a character at the lower-right corner more
  114.      * than once, fail.  (Moving the cursor will clear the flag).
  115.      */
  116. #if 0                /* Solaris 2.6 allows updating the corner more than once */
  117.     if (win->_flags & _WRAPPED) {
  118.     if (x >= win->_maxx)
  119.         return (ERR);
  120.     win->_flags &= ~_WRAPPED;
  121.     }
  122. #endif
  123.  
  124.     ch = render_char(win, ch);
  125.     TR(TRACE_VIRTPUT, ("win attr = %s", _traceattr(win->_attrs)));
  126.  
  127.     line = win->_line + win->_cury;
  128.  
  129.     CHANGED_CELL(line, x);
  130.  
  131.     /*
  132.      * Handle non-spacing characters
  133.      */
  134.     if_WIDEC({
  135.     if (wcwidth(CharOf(ch)) == 0) {
  136.         int i;
  137.         int y;
  138.         if ((x > 0 && ((y = win->_cury) >= 0))
  139.         || ((y = win->_cury - 1) >= 0 &&
  140.             (x = win->_maxx) > 0)) {
  141.         wchar_t *chars = (win->_line[y].text[x - 1].chars);
  142.         for (i = 0; i < CCHARW_MAX; ++i) {
  143.             if (chars[i] == 0) {
  144.             chars[i] = CharOf(ch);
  145.             break;
  146.             }
  147.         }
  148.         }
  149.         goto testwrapping;
  150.     }
  151.     });
  152.     line->text[x++] = ch;
  153.     /*
  154.      * Provide for multi-column characters
  155.      */
  156.     if_WIDEC({
  157.     if (wcwidth(CharOf(ch)) > 1)
  158.         AddAttr(line->text[x++], WA_NAC);
  159.     }
  160.   testwrapping:
  161.     );
  162.  
  163.     TR(TRACE_VIRTPUT, ("(%d, %d) = %s", win->_cury, x, _tracech_t(CHREF(ch))));
  164.     if (x > win->_maxx) {
  165.     /*
  166.      * The _WRAPPED flag is useful only for telling an application that
  167.      * we've just wrapped the cursor.  We don't do anything with this flag
  168.      * except set it when wrapping, and clear it whenever we move the
  169.      * cursor.  If we try to wrap at the lower-right corner of a window, we
  170.      * cannot move the cursor (since that wouldn't be legal).  So we return
  171.      * an error (which is what SVr4 does).  Unlike SVr4, we can
  172.      * successfully add a character to the lower-right corner (Solaris 2.6
  173.      * does this also, however).
  174.      */
  175.     win->_flags |= _WRAPPED;
  176.     if (++win->_cury > win->_regbottom) {
  177.         win->_cury = win->_regbottom;
  178.         win->_curx = win->_maxx;
  179.         if (!win->_scroll)
  180.         return (ERR);
  181.         scroll(win);
  182.     }
  183.     win->_curx = 0;
  184.     return (OK);
  185.     }
  186.     win->_curx = x;
  187.     return OK;
  188. }
  189.  
  190. static inline int
  191. waddch_nosync(WINDOW *win, const NCURSES_CH_T ch)
  192. /* the workhorse function -- add a character to the given window */
  193. {
  194.     int x, y;
  195.     chtype t = 0;
  196.     const char *s = 0;
  197.  
  198.     if ((AttrOf(ch) & A_ALTCHARSET)
  199.     || ((t = CharOf(ch)) > 127)
  200.     || ((s = unctrl(t))[1] == 0))
  201.     return waddch_literal(win, ch);
  202.  
  203.     x = win->_curx;
  204.     y = win->_cury;
  205.  
  206.     switch (t) {
  207.     case '\t':
  208.     x += (TABSIZE - (x % TABSIZE));
  209.  
  210.     /*
  211.      * Space-fill the tab on the bottom line so that we'll get the
  212.      * "correct" cursor position.
  213.      */
  214.     if ((!win->_scroll && (y == win->_regbottom))
  215.         || (x <= win->_maxx)) {
  216.         NCURSES_CH_T blank = NewChar2(BLANK_TEXT, BLANK_ATTR);
  217.         AddAttr(blank, AttrOf(ch));
  218.         while (win->_curx < x) {
  219.         if (waddch_literal(win, blank) == ERR)
  220.             return (ERR);
  221.         }
  222.         break;
  223.     } else {
  224.         wclrtoeol(win);
  225.         win->_flags |= _WRAPPED;
  226.         if (++y > win->_regbottom) {
  227.         x = win->_maxx;
  228.         y--;
  229.         if (win->_scroll) {
  230.             scroll(win);
  231.             x = 0;
  232.         }
  233.         } else {
  234.         x = 0;
  235.         }
  236.     }
  237.     break;
  238.     case '\n':
  239.     wclrtoeol(win);
  240.     if (++y > win->_regbottom) {
  241.         y--;
  242.         if (win->_scroll)
  243.         scroll(win);
  244.         else
  245.         return (ERR);
  246.     }
  247.     /* FALLTHRU */
  248.     case '\r':
  249.     x = 0;
  250.     win->_flags &= ~_WRAPPED;
  251.     break;
  252.     case '\b':
  253.     if (x == 0)
  254.         return (OK);
  255.     x--;
  256.     win->_flags &= ~_WRAPPED;
  257.     break;
  258.     default:
  259.     while (*s) {
  260.         NCURSES_CH_T sch;
  261.         SetChar(sch, *s++, AttrOf(ch));
  262.         if (waddch_literal(win, sch) == ERR)
  263.         return ERR;
  264.     }
  265.     return (OK);
  266.     }
  267.  
  268.     win->_curx = x;
  269.     win->_cury = y;
  270.  
  271.     return (OK);
  272. }
  273.  
  274. NCURSES_EXPORT(int)
  275. _nc_waddch_nosync(WINDOW *win, const NCURSES_CH_T c)
  276. /* export copy of waddch_nosync() so the string-put functions can use it */
  277. {
  278.     return (waddch_nosync(win, c));
  279. }
  280.  
  281. /*
  282.  * The versions below call _nc_synhook().  We wanted to avoid this in the
  283.  * version exported for string puts; they'll call _nc_synchook once at end
  284.  * of run.
  285.  */
  286.  
  287. /* These are actual entry points */
  288.  
  289. NCURSES_EXPORT(int)
  290. waddch(WINDOW *win, const chtype ch)
  291. {
  292.     int code = ERR;
  293.     NCURSES_CH_T wch;
  294.     SetChar2(wch, ch);
  295.  
  296.     TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("waddch(%p, %s)"), win,
  297.                       _tracechtype(ch)));
  298.  
  299.     if (win && (waddch_nosync(win, wch) != ERR)) {
  300.     _nc_synchook(win);
  301.     code = OK;
  302.     }
  303.  
  304.     TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code));
  305.     return (code);
  306. }
  307.  
  308. NCURSES_EXPORT(int)
  309. wechochar(WINDOW *win, const chtype ch)
  310. {
  311.     int code = ERR;
  312.     NCURSES_CH_T wch;
  313.     SetChar2(wch, ch);
  314.  
  315.     TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wechochar(%p, %s)"), win,
  316.                       _tracechtype(ch)));
  317.  
  318.     if (win && (waddch_nosync(win, wch) != ERR)) {
  319.     bool save_immed = win->_immed;
  320.     win->_immed = TRUE;
  321.     _nc_synchook(win);
  322.     win->_immed = save_immed;
  323.     code = OK;
  324.     }
  325.     TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code));
  326.     return (code);
  327. }
  328.  
  329. #if USE_WIDEC_SUPPORT
  330. NCURSES_EXPORT(int)
  331. wadd_wch(WINDOW *win, const cchar_t * wch)
  332. {
  333.     int code = ERR;
  334.  
  335.     TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wadd_wch(%p, %s)"), win,
  336.                       _tracech_t(wch)));
  337.  
  338.     if (win && (waddch_nosync(win, *wch) != ERR)) {
  339.     _nc_synchook(win);
  340.     code = OK;
  341.     }
  342.  
  343.     TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code));
  344.     return (code);
  345. }
  346.  
  347. NCURSES_EXPORT(int)
  348. wecho_wchar(WINDOW *win, const cchar_t * wch)
  349. {
  350.     int code = ERR;
  351.  
  352.     TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wecho_wchar(%p, %s)"), win,
  353.                       _tracech_t(wch)));
  354.  
  355.     if (win && (waddch_nosync(win, *wch) != ERR)) {
  356.     bool save_immed = win->_immed;
  357.     win->_immed = TRUE;
  358.     _nc_synchook(win);
  359.     win->_immed = save_immed;
  360.     code = OK;
  361.     }
  362.     TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code));
  363.     return (code);
  364. }
  365. #endif /* USE_WIDEC_SUPPORT */
  366.